﻿using JESAI.DynamicWebApi.Attributes;
using JESAI.DynamicWebApi.Configurations;
using JESAI.DynamicWebApi.Helpers;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.DependencyInjection;
using Panda.DynamicWebApi.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace JESAI.DynamicWebApi.Providers
{
    /// <summary>
    /// 重写ControllerFeatureProvider
    /// </summary>
    public class DynamicWebApiControllerFeatureProvider : ControllerFeatureProvider
    {
        public IServiceCollection _services;
        public DynamicWebApiControllerFeatureProvider(IServiceCollection services)
        {
            _services = services;
        }
        /// <summary>
        /// 重写ControllerFeatureProvider里面判断是否是控制器（IsController）方法
        /// </summary>
        /// <param name="typeInfo">TypeInfo实例</param>
        /// <returns></returns>
        protected override bool IsController(TypeInfo typeInfo)
        {
            var type = typeInfo.AsType();

            ////判断type是否是IDynamicWebApiService的子类，如果是不是子类，
            ///或者不是Public类型，
            ///或者是抽象Abstract类，
            ///或者是泛型，则不是控制器。
            if (!typeof(IDynamicWebApiService).IsAssignableFrom(type) ||
                !typeInfo.IsPublic || typeInfo.IsAbstract || typeInfo.IsGenericType)
            {
                return false;
            }

            ///获取typeInfo的DynamicWebApiAttribute，如果不为空，则判断是否启用(Enabled=true)则继续,如果不空，且不启用(Enabled=false)，则不是控制器
            //TO-DO:这里有一个设想，可以直接使用DynamicWebApiAttribute来暴露控制器，待实验。
            var dynamicWebApiAttr = ReflectionHelper.GetSingleAttributeOrDefault<DynamicWebApiAttribute>(typeInfo);

            if (dynamicWebApiAttr != null && !dynamicWebApiAttr.IsEnabledFor(type))
            {
                return false;
            }

            ///先从DI里面获取注入的配置信息
            ///然后过滤拿到当前程序集的配置信息
            var settings = _services.GetSingletonInstance<IDynamicWebApiConfiguration>().dynamicWebApiControllerAssemblySettings.GetSettings(type);
            return settings.Any(setting => setting.TypePredicate(type));
        }
    }
}
